home *** CD-ROM | disk | FTP | other *** search
- #define VERSION "sz 1.23 01-15-87"
- #define PUBDIR "/usr/spool/uucppublic"
-
- /*% cc -O -K -i -DCRCTABLE -DREADCHECK sz.c -lx -o sz; size sz
-
- * sz.c By Chuck Forsberg
- * MS-DOS version by Francois Bergeon
- *
- * cc -O sz.c -o sz USG (SYS III/V) Unix
- * cc -O -DSVR2 sz.c -o sz Sys V Release 2 with non-blocking input
- * Define to allow reverse channel checking
- * cc -O -DV7 sz.c -o sz Unix Version 7, 2.8 - 4.3 BSD
- * cl rz.c -link stty MS-DOS, MS-C 4.00+
- *
- * ln sz sb USG & V7
- *
- * define CRCTABLE to use table driven CRC
- *
- * ******* Some systems (Venix, Coherent, Regulus) do not *******
- * ******* support tty raw mode read(2) identically to *******
- * ******* Unix. ONEREAD must be defined to force one *******
- * ******* character reads for these systems. *******
- *
- * A program for Unix to send files and commands to computers running
- * Professional-YAM, PowerCom, YAM, IMP, or programs supporting Y/XMODEM.
- *
- * Sz uses buffered I/O to greatly reduce CPU time compared to UMODEM.
- *
- * USG UNIX (3.0) ioctl conventions courtesy Jeff Martin
- *
- * MS-DOS Adaptation 10-19-87 for the MS-C compiler rev 4.00+
- * using Francois Bergeon's tty library
- */
-
-
- char *substr(), *getenv();
-
- #define LOGFILE "/tmp/szlog"
-
- #include <stdio.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <ctype.h>
-
- #ifdef MSDOS
- #include <time.h>
- #define CRCTABLE
- #define JAN1ST70 315532800 /* difference in seconds between */
- /* Jan 1st 1980 & Jan 1st 1970 */
- #endif
-
- #define PATHLEN 256
- #define OK 0
- #define FALSE 0
- #define TRUE 1
- #define ERROR (-1)
-
- #define HOWMANY 2
- int Zmodem = 0; /* ZMODEM protocol requested */
- unsigned Baudrate;
- int Fromcu = 0; /* Were called from cu or yam */
- #include "rbsb.c" /* most of the system dependent stuff here */
-
- /*
- * Attention string to be executed by receiver to interrupt streaming data
- * when an error is detected. A pause (0336) may be needed before the
- * ^C (03) or after it.
- */
- #ifdef READCHECK
- char Myattn[] = { 0 };
- #else
- #ifdef USG
- char Myattn[] = { 03, 0336, 0 };
- #else
- char Myattn[] = { 0 };
- #endif
- #endif
-
- FILE *in;
-
- /* Ward Christensen / CP/M parameters - Don't change these! */
- #define ENQ 005
- #define CAN ('X'&037)
- #define XOFF ('s'&037)
- #define XON ('q'&037)
- #define SOH 1
- #define STX 2
- #define EOT 4
- #define ACK 6
- #define NAK 025
- #define CPMEOF 032
- #define WANTCRC 0103 /* send C not NAK to get crc not checksum */
- #define WANTG 0107 /* Send G not NAK to get nonstop batch xmsn */
- #define TIMEOUT (-2)
- #define RCDO (-3)
- #define RETRYMAX 10
- #define SECSIZ 128 /* cp/m's Magic Number record size */
- #define KSIZE 1024
-
- char Lastrx;
- char Crcflg;
- int Wcsmask = 0377;
- int Verbose = 0;
- int Modem = 0; /* MODEM - don't send pathnames */
- int Restricted = 0; /* restricted; no /.. or ../ in filenames */
- int Quiet = 0; /* overrides logic that would otherwise set verbose */
- int Ascii = 0; /* Add CR's for brain damaged programs */
- int Fullname = 0; /* transmit full pathname */
- int Unlinkafter = 0; /* Unlink file after it is sent */
- int Dottoslash = 0; /* Change foo.bar.baz to foo/bar/baz */
- int firstsec;
- int errcnt = 0; /* number of files unreadable */
- int blklen = SECSIZ; /* length of transmitted records */
- int Optiong; /* Let it rip no wait for sector ACK's */
- int Noeofseen;
- int Totsecs; /* total number of sectors this file */
- char txbuf[KSIZE];
- int Filcnt = 0; /* count of number of files opened */
- int Lfseen = 0;
- unsigned Rxbuflen = 16384; /* Receiver's max buffer length */
- int Tframlen = 0; /* Override for tx frame length */
- int blkopt = 0; /* Override value for zmodem blklen */
- int Rxflags = 0;
- int Wantfcs32 = TRUE; /* want to send 32 bit FCS */
- char Lzconv; /* Local ZMODEM file conversion request */
- char Lzmanag; /* Local ZMODEM file management request */
- char Lztrans;
- char zconv; /* ZMODEM file conversion request */
- char zmanag; /* ZMODEM file management request */
- char ztrans; /* ZMODEM file transport request */
- int Command; /* Send a command, then exit. */
- char *Cmdstr; /* Pointer to the command string */
- int Cmdtries = 11;
- int Cmdack1; /* Rx ACKs command, then do it */
- int Exitcode;
- int Testattn; /* Force receiver to send Attn, etc with qbf. */
- char *qbf="The quick brown fox jumped over the lazy dog's back 1234567890\r\n";
- long Lastread; /* Beginning offset of last buffer read */
- int Lastc; /* Count of last buffer read or -1 */
- int Dontread; /* Don't read the buffer, it's still there */
-
- #ifndef MSDOS
- jmp_buf tohere; /* For the interrupt on RX timeout */
- #endif
-
- jmp_buf intrjmp; /* For the interrupt on RX CAN */
-
- /* called by signal interrupt or terminate to clean things up */
- bibi(n)
- {
- canit();
- fflush(stdout);
- mode(0);
- fprintf(stderr, "sz: caught signal %d; exiting\n", n);
- #ifndef MSDOS
- if (n == SIGQUIT)
- abort();
- #endif
- exit(128+n);
- }
- /* Called when Zmodem gets an interrupt (^X) */
-
- onintr()
- {
- signal(SIGINT, SIG_IGN);
- longjmp(intrjmp, -1);
- }
-
- #ifndef MSDOS
- #define sendline(c) putchar(c & Wcsmask)
- #define xsendline(c) putchar(c)
-
- flushmo()
- {
- fflush(stdout);
- }
-
- #else /* MSDOS */
-
- #define sendline(c) xsendline(c & Wcsmask)
-
- xsendline(c)
- int c;
- {
- tty_write(iofd, &c, 1);
- }
-
- flushmo()
- {
- }
- #endif
-
- #define ZKER
- int Zctlesc; /* Encode control characters */
- int Nozmodem = 0; /* If invoked as "sb" */
- char *Progname = "sz";
- #include "zm.c"
-
-
- main(argc, argv)
- char *argv[];
- {
- char *cp;
- int npats;
- int agcnt;
- char **agcv;
- char **patts;
- static char xXbuf[BUFSIZ];
-
- if ((cp = getenv("ZNULLS")) && *cp)
- Znulls = atoi(cp);
- if ((cp = getenv("SHELL")) && (substr(cp, "rsh") || substr(cp, "rksh")))
- Restricted = TRUE;
- #ifndef MSDOS
- chkinvok(argv[0]);
- #else
- Progname = "sz";
- #endif
-
- Rxtimeout = 600;
- npats = 0;
- if (argc < 2)
- usage();
- setbuf(stdout, xXbuf);
- while (--argc)
- {
- cp = *++argv;
- if (*cp++ == '-' && *cp)
- {
- while (*cp)
- {
- switch (*cp++)
- {
- case '+':
- Lzmanag = ZMAPND;
- break;
- #ifndef MSDOS
- case '1':
- iofd = 1;
- break;
- #ifdef CSTOPB
- case '2':
- Twostop = TRUE;
- break;
- #endif
- #else
- case '2':
- port = "COM2";
- break;
- case 's':
- Baudrate = atoi(cp);
- if ((speed = getspeed(Baudrate)) < 0)
- usage();
- cp = '\0';
- break;
- case 'Y':
- Nozmodem = TRUE;
- break;
- #endif
- case '7':
- Wcsmask=0177;
- break;
- case 'a':
- Lzconv = ZCNL;
- Ascii = TRUE;
- break;
- case 'b':
- Lzconv = ZCBIN;
- break;
- case 'C':
- if (--argc < 1)
- usage();
- Cmdtries = atoi(*++argv);
- break;
- case 'i':
- Cmdack1 = ZCACK1;
- /* **** FALL THROUGH TO **** */
- case 'c':
- if (--argc != 1)
- usage();
- Command = TRUE;
- Cmdstr = *++argv;
- break;
- case 'd':
- ++Dottoslash;
- /* **** FALL THROUGH TO **** */
- case 'f':
- Fullname=TRUE;
- break;
- case 'E':
- Zctlesc = -1;
- break;
- case 'e':
- Zctlesc = 1;
- break;
- case 'k':
- blklen = KSIZE;
- break;
- case 'L':
- if (--argc < 1)
- usage();
- blkopt = atoi(*++argv);
- if (blkopt < 24 || blkopt > 1024)
- usage();
- break;
- case 'l':
- if (--argc < 1)
- usage();
- Tframlen = atoi(*++argv);
- if (Tframlen < 32 || Tframlen > 1024)
- usage();
- break;
- case 'N':
- Lzmanag = ZMDIFF;
- break;
- case 'n':
- Lzmanag = ZMNEW;
- break;
- case 'o':
- Wantfcs32 = FALSE;
- break;
- case 'p':
- Lzmanag = ZMPROT;
- break;
- case 'r':
- Lzconv = ZCRESUM;
- case 'q':
- Quiet = TRUE;
- Verbose = 0;
- break;
- case 't':
- if (--argc < 1)
- usage();
- Rxtimeout = atoi(*++argv);
- if (Rxtimeout < 10 || Rxtimeout > 1000)
- usage();
- break;
- case 'T':
- Testattn = TRUE;
- break;
- case 'u':
- ++Unlinkafter;
- break;
- case 'v':
- ++Verbose;
- break;
- case 'X':
- ++Modem;
- break;
- case 'y':
- Lzmanag = ZMCLOB;
- break;
- default:
- usage();
- }
- }
- }
- else if (!npats && argc > 0)
- {
- if (argv[0][0])
- {
- npats = argc;
- patts = argv;
- #ifndef MSDOS
- if (!strcmp(*patts, "-"))
- iofd = 1;
- #endif
- }
- }
- }
- if (npats < 1 && !Command)
- usage();
- if (Verbose)
- {
- if (freopen(LOGFILE, "a", stderr) == NULL)
- {
- printf("Can't open log file %s\n",LOGFILE);
- exit(0200);
- }
- setbuf(stderr, NULL);
- }
- if ((Fromcu = from_cu()) && !Quiet)
- if (!Verbose)
- Verbose = 2;
-
- mode(1);
-
- if (signal(SIGINT, bibi) == SIG_IGN)
- {
- signal(SIGINT, SIG_IGN);
- #ifndef MSDOS
- signal(SIGKILL, SIG_IGN);
- #endif
- }
- else
- {
- signal(SIGINT, bibi);
- #ifndef MSDOS
- signal(SIGKILL, bibi);
- #endif
- }
- #ifndef MSDOS
- if (!Fromcu)
- signal(SIGQUIT, SIG_IGN);
- #endif
-
- if (!Modem)
- {
- if (!Nozmodem)
- {
- #ifndef MSDOS
- printf("rz\r");
- fflush(stdout);
- #else
- tty_write(iofd, "rz\r", 3);
- #endif
- }
- if (!Command && !Quiet && Verbose != 1)
- {
- fprintf(stderr, "%s: %d file%s requested:\r\n",
- Progname, npats, (npats > 1 ? "s" : ""));
- for (agcnt = npats, agcv = patts; --agcnt >= 0; )
- fprintf(stderr, "%s ", *agcv++);
- fprintf(stderr, "\r\n");
- #ifndef MSDOS
- printf("\r\n\bSending in Batch Mode\r\n");
- #else
- tty_write(iofd, "\r\n\bSending in Batch Mode\r\n", 26);
- #endif
- }
- if (!Nozmodem)
- {
- stohdr(0L);
- if (Command)
- Txhdr[ZF0] = ZCOMMAND;
- zshhdr(ZRQINIT, Txhdr);
- }
- }
- fflush(stdout);
-
- if (Command)
- {
- if (getzrxinit())
- {
- Exitcode=0200;
- canit();
- }
- else if (zsendcmd(Cmdstr, 1+strlen(Cmdstr)))
- {
- Exitcode=0200;
- canit();
- }
- }
- else if (wcsend(npats, patts) == ERROR)
- {
- Exitcode=0200;
- canit();
- }
- fflush(stdout);
- mode(0);
- exit((errcnt != 0) | Exitcode);
- /*NOTREACHED*/
- }
-
- wcsend(argc, argp)
- char *argp[];
- {
- int n;
-
- Crcflg = FALSE;
- firstsec = TRUE;
- for (n = 0; n < argc; ++n)
- {
- Totsecs = 0;
- if (wcs(argp[n]) == ERROR)
- return(ERROR);
- }
- Totsecs = 0;
- if (Filcnt == 0)
- {
- /* bitch if we couldn't open ANY files */
- if (1)
- {
- Command = TRUE;
- Cmdstr = "echo \"sz: Can't open any requested files\"";
- if (getnak())
- {
- Exitcode = 0200;
- canit();
- }
- if (!Zmodem)
- canit();
- else if (zsendcmd(Cmdstr, 1 + strlen(Cmdstr)))
- {
- Exitcode=0200;
- canit();
- }
- Exitcode = 1;
- return(OK);
- }
- canit();
- fprintf(stderr, "\r\nCan't open any requested files.\r\n");
- return(ERROR);
- }
- if (Zmodem)
- saybibi();
- else
- wctxpn("");
- return(OK);
- }
-
- wcs(oname)
- char *oname;
- {
- int c;
- char *p;
- struct stat f;
- char name[PATHLEN];
-
- strcpy(name, oname);
-
- if (Restricted)
- {
- /* restrict pathnames to current tree or uucppublic */
- if (substr(name, "../")
- || (name[0]== '/' && strncmp(name, PUBDIR, strlen(PUBDIR))))
- {
- canit();
- fprintf(stderr, "\r\nsz:\tSecurity Violation\r\n");
- return(ERROR);
- }
- }
-
- if (!strcmp(oname, "-"))
- {
- if ((p = getenv("ONAME")) && *p)
- strcpy(name, p);
- else
- sprintf(name, "s%d.sz", getpid());
- in = stdin;
- }
- #ifndef MSDOS
- else if ((in = fopen(oname, "r")) == NULL)
- #else
- else if ((in = fopen(oname, "rb")) == NULL)
- #endif
- {
- ++errcnt;
- return(OK); /* pass over it, there may be others */
- }
- ++Noeofseen;
- Lastread = 0;
- Lastc = -1;
- Dontread = FALSE;
- /* Check for directory or block special files */
- fstat(fileno(in), &f);
- c = f.st_mode & S_IFMT;
- #ifndef MSDOS
- if (c == S_IFDIR || c == S_IFBLK)
- #else
- if (c == S_IFDIR)
- #endif
- {
- fclose(in);
- return(OK);
- }
-
- ++Filcnt;
- switch (wctxpn(name))
- {
- case ERROR:
- return(ERROR);
- case ZSKIP:
- return(OK);
- }
- if (!Zmodem && wctx() == ERROR)
- return(ERROR);
- if (Unlinkafter)
- unlink(oname);
- return(0);
- }
-
- /*
- * generate and transmit pathname block consisting of
- * pathname (null terminated),
- * file length, mode time and file mode in octal
- * as provided by the Unix fstat call.
- * N.B.: modifies the passed name, may extend it!
- */
- wctxpn(name)
- char *name;
- {
- char *p, *q;
- char name2[PATHLEN];
- struct stat f;
-
- if (Modem)
- {
- if ((in != stdin) && *name && fstat(fileno(in), &f) != -1)
- fprintf(stderr, "Sending %s, %ld blocks: ", name, f.st_size >> 7);
- fprintf(stderr, "Give your local XMODEM receive command now.\r\n");
- return(OK);
- }
- logent("\r\nAwaiting pathname nak for %s\r\n", *name ? name : "<END>");
- if (!Zmodem)
- if (getnak())
- return(ERROR);
-
- q = (char *) 0;
- if (Dottoslash)
- {
- /* change . to . */
- for (p = name; *p; ++p)
- {
- if (*p == '/')
- q = p;
- else if (*p == '.')
- *(q=p) = '/';
- }
- if (q && strlen(++q) > 8)
- {
- /* If name>8 chars */
- q += 8; /* make it .ext */
- strcpy(name2, q); /* save excess of name */
- *q = '.';
- strcpy(++q, name2); /* add it back */
- }
- }
-
- for (p = name, q = txbuf; *p; )
- if ((*q++ = *p++) == '/' && !Fullname)
- q = txbuf;
- *q++ = 0;
- p = q;
- while (q < (txbuf + KSIZE))
- *q++ = 0;
- if (!Ascii && (in != stdin) && *name && fstat(fileno(in), &f) != -1)
- #ifndef MSDOS
- sprintf(p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
- #else
- sprintf(p, "%lu %lo %o", f.st_size, f.st_mtime + JAN1ST70, f.st_mode);
- #endif
- /* force 1k blocks if name won't fit in 128 byte block */
- if (txbuf[125])
- blklen = KSIZE;
- else
- {
- /* A little goodie for IMP/KMD */
- if (Zmodem)
- blklen = SECSIZ;
- txbuf[127] = (f.st_size + 127) >> 7;
- txbuf[126] = (f.st_size + 127) >> 15;
- }
- if (Zmodem)
- return(zsendfile(txbuf, 1+strlen(p)+(p-txbuf)));
- if (wcputsec(txbuf, 0, SECSIZ) == ERROR)
- return(ERROR);
- return(OK);
- }
-
- getnak()
- {
- int firstch;
-
- Lastrx = 0;
- for (;;)
- {
- switch (firstch = readock(800,1))
- {
- case ZPAD:
- if (getzrxinit())
- return(ERROR);
- Ascii = 0;
- return(FALSE);
- case TIMEOUT:
- logent("Timeout on pathname\n");
- return(TRUE);
- case WANTG:
- #ifdef USG
- mode(2); /* Set cbreak, XON/XOFF, etc. */
- #endif
- Optiong = TRUE;
- blklen = KSIZE;
- case WANTCRC:
- Crcflg = TRUE;
- case NAK:
- return(FALSE);
- case CAN:
- if ((firstch = readock(20,1)) == CAN && Lastrx == CAN)
- return(TRUE);
- default:
- break;
- }
- Lastrx = firstch;
- }
- }
-
-
- wctx()
- {
- int sectnum, attempts, firstch;
-
- firstsec = TRUE;
-
- while ((firstch = readock(Rxtimeout, 2)) !=NAK && firstch != WANTCRC
- && firstch != WANTG && firstch != TIMEOUT && firstch != CAN)
- {;}
- if (firstch == CAN)
- {
- logent("Receiver CANcelled\n");
- return(ERROR);
- }
- if (firstch == WANTCRC)
- Crcflg = TRUE;
- if (firstch == WANTG)
- Crcflg = TRUE;
- sectnum = 1;
- while (filbuf(txbuf, blklen))
- if (wcputsec(txbuf, sectnum, blklen) == ERROR)
- return(ERROR);
- else
- sectnum++;
- if (Verbose > 1)
- fprintf(stderr, " Closing ");
- fclose(in);
- attempts = 0;
- do
- {
- logent(" EOT ");
- purgeline();
- sendline(EOT);
- fflush(stdout);
- ++attempts;
- }
- while ((firstch = (readock(Rxtimeout, 1)) != ACK) && attempts < RETRYMAX);
- if (attempts == RETRYMAX)
- {
- logent("No ACK on EOT\n");
- return(ERROR);
- }
- else
- return(OK);
- }
-
- wcputsec(buf, sectnum, cseclen)
- char *buf;
- int sectnum;
- int cseclen; /* data length of this sector to send */
- {
- int checksum, wcj;
- char *cp;
- unsigned oldcrc;
- int firstch;
- int attempts;
-
- firstch = 0; /* part of logic to detect CAN CAN */
-
- if (Verbose > 1)
- fprintf(stderr, "\rSector %3d %2dk ", Totsecs, Totsecs/8 );
- for (attempts = 0; attempts <= RETRYMAX; attempts++)
- {
- Lastrx = firstch;
- sendline(cseclen == KSIZE ? STX : SOH);
- sendline(sectnum);
- sendline(-sectnum -1);
- oldcrc = checksum = 0;
- for (wcj = cseclen, cp = buf; --wcj >= 0; )
- {
- sendline(*cp);
- oldcrc = updcrc((0377& *cp), oldcrc);
- checksum += *cp++;
- }
- if (Crcflg)
- {
- oldcrc = updcrc(0, updcrc(0, oldcrc));
- sendline((int)oldcrc >> 8);
- sendline((int)oldcrc);
- }
- else
- sendline(checksum);
-
- if (Optiong)
- {
- firstsec = FALSE;
- return(OK);
- }
- firstch = readock(Rxtimeout, (Noeofseen && sectnum) ? 2 : 1);
- gotnak:
- switch (firstch)
- {
- case CAN:
- if (Lastrx == CAN)
- {
- cancan:
- logent("Cancelled\n");
- return(ERROR);
- }
- break;
- case TIMEOUT:
- logent("Timeout on sector ACK\n");
- continue;
- case WANTCRC:
- if (firstsec)
- Crcflg = TRUE;
- case NAK:
- logent("NAK on sector\n");
- continue;
- case ACK:
- firstsec = FALSE;
- Totsecs += (cseclen >> 7);
- return(OK);
- case ERROR:
- logent("Got burst for sector ACK\n");
- break;
- default:
- logent("Got %02x for sector ACK\n", firstch);
- break;
- }
- for (;;)
- {
- Lastrx = firstch;
- if ((firstch = readock(Rxtimeout, 2)) == TIMEOUT)
- break;
- if (firstch == NAK || firstch == WANTCRC)
- goto gotnak;
- if (firstch == CAN && Lastrx == CAN)
- goto cancan;
- }
- }
- logent("Retry Count Exceeded\n");
- return(ERROR);
- }
-
- /* fill buf with count chars padding with ^Z for CPM */
- filbuf(buf, count)
- char *buf;
- {
- int c, m;
-
- if (!Ascii)
- {
- m = read(fileno(in), buf, count);
- if (m <= 0)
- return(0);
- while (m < count)
- buf[m++] = 032;
- return(count);
- }
- m = count;
- if (Lfseen)
- {
- *buf++ = 012;
- --m;
- Lfseen = 0;
- }
- while ((c = getc(in)) != EOF)
- {
- if (c == 012)
- {
- *buf++ = 015;
- if (--m == 0)
- {
- Lfseen = TRUE;
- break;
- }
- }
- *buf++ = c;
- if (--m == 0)
- break;
- }
- if (m == count)
- return(0);
- else
- while (--m >= 0)
- *buf++ = CPMEOF;
- return(count);
- }
-
- /* fill buf with count chars */
- zfilbuf(buf, count)
- char *buf;
- {
- int c, m;
-
- m = count;
- while ((c = getc(in)) != EOF)
- {
- *buf++ =c;
- if (--m == 0)
- break;
- }
- return(count - m);
- }
-
- /* VARARGS1 */
- vfile(f, a, b, c)
- char *f;
- {
- if (Verbose > 2)
- {
- fprintf(stderr, f, a, b, c);
- fprintf(stderr, "\n");
- }
- }
-
- zperr(f, a, b, c)
- char *f;
- {
- if (Verbose > 1)
- {
- fprintf(stderr, f, a, b, c);
- fprintf(stderr, "\n");
- }
- }
-
- #ifndef MSDOS
- alrm()
- {
- longjmp(tohere, -1);
- }
- #endif
-
- /*
- * readock(timeout, count) reads character(s) from file descriptor 0
- * (1 <= count <= 3)
- * it attempts to read count characters. If it gets more than one,
- * it is an error unless all are CAN
- * (otherwise, only normal response is ACK, CAN, or C)
- * Only looks for one if Optiong, which signifies cbreak, not raw input
- *
- * timeout is in tenths of seconds
- */
- readock(timeout, count)
- int timeout, count;
- {
- int c, n;
- static char byt[5];
- #ifdef MSDOS
- time_t start;
- #endif
-
- if (Optiong)
- count = 1; /* Special hack for cbreak */
-
- fflush(stdout);
- n = timeout/10;
- if (n < 2)
- n = 2;
- if (Verbose > 3)
- {
- fprintf(stderr, "Timeout=%d Calling alarm(%d) ", timeout, n);
- byt[1] = 0;
- }
- #ifndef MSDOS
- if (setjmp(tohere))
- {
- logent("TIMEOUT\n");
- return(TIMEOUT);
- }
- signal(SIGALRM, alrm);
- alarm(n);
- #ifdef ONEREAD
- c = read(iofd, byt, 1); /* regulus raw read is unique */
- #else
- c = read(iofd, byt, count);
- #endif
- alarm(0);
- #else /* MSDOS */
- time(&start);
- #ifdef ONEREAD
- while (!(c = tty_read(iofd, byt, 1)) && /* regulus raw read is unique */
- (int)difftime(time(NULL), start) < n)
- {;}
- #else
- while (!(c = tty_read(iofd, byt, count)) &&
- (int)difftime(time(NULL), start) < n)
- {;}
- #endif
- if (!c)
- {
- logent("TIMEOUT\n");
- return(TIMEOUT);
- }
- #endif /* MSDOS */
- if (Verbose > 5)
- fprintf(stderr, "ret cnt=%d %x %x\n", c, byt[0], byt[1]);
- if (c < 1)
- return(TIMEOUT);
- if (c == 1)
- return (byt[0] & 0377);
- else
- while (c)
- if (byt[--c] != CAN)
- return(ERROR);
- return(CAN);
- }
-
- readline(n)
- {
- return(readock(n, 1));
- }
-
-
- purgeline()
- {
- #ifdef USG
- ioctl(iofd, TCFLSH, 0);
- #endif
- #ifdef V7
- lseek(iofd, 0L, 2);
- #endif
- #ifdef MSDOS
- char c;
-
- while (tty_read(iofd, &c, 1))
- {;}
- #endif
- }
-
-
- /* send cancel string to get the other end to shut up */
- canit()
- {
- static char canistr[] =
- {
- 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
- };
-
- #ifndef MSDOS
- printf(canistr);
- fflush(stdout);
- #else
- tty_write(iofd, canistr, strlen(canistr));
- #endif
- }
-
- /*VARARGS1*/
- logent(a, b, c)
- char *a, *b, *c;
- {
- if (Verbose > 1)
- fprintf(stderr, a, b, c);
- }
-
- /*
- * return 1 iff stdout and stderr are different devices
- * indicating this program operating with a modem on a
- * different line
- */
- from_cu()
- {
- #ifndef MSDOS
- struct stat a, b;
- fstat(1, &a);
- fstat(2, &b);
- return(a.st_rdev != b.st_rdev);
- #else
- return(1);
- #endif
- }
-
- /*
- * substr(string, token) searches for token in string s
- * returns pointer to token within string if found, NULL otherwise
- */
- char *substr(s, t)
- char *s,*t;
- {
- char *ss,*tt;
- /* search for first char of token */
- for (ss = s; *s; s++)
- if (*s == *t)
- /* compare token with substring */
- for (ss = s, tt = t; ; )
- {
- if (*tt == 0)
- return(s);
- if (*ss++ != *tt++)
- break;
- }
- return(NULL);
- }
-
- char *babble[] =
- {
- "Send file(s) with ZMODEM/YMODEM/XMODEM Protocol",
- " (Y) = Option applies to YMODEM only",
- " (Z) = Option applies to ZMODEM only",
- #ifndef MSDOS
- "Usage: sz [-12+aBbdefkLlNnquvXy] [-] file ...",
- " sz [-1Beqv] -c COMMAND",
- " 1 Use stdout for modem input",
- #ifdef CSTOPB
- " 2 Use 2 stop bits",
- #endif
- #else
- "Usage: sz [-2+aBbdefkLlNnquvXYy] [-s<speed>] [-] file ...",
- " sz [-2Beqv] [-s<speed>] -c COMMAND",
- " 2 Use COM2 instead of COM1",
- #endif
- " + Append to existing destination file (Z)",
- " a (ASCII) change NL to CR/LF",
- " b Binary file transfer override",
- " c send COMMAND (Z)",
- " d Change '.' to '/' in pathnames (Y/Z)",
- " e Escape all control characters (Z)",
- " f send Full pathname (Y/Z)",
- " i send COMMAND, ack Immediately (Z)",
- " k Send 1024 byte packets (Y)",
- " L N Limit subpacket length to N bytes (Z)",
- " l N Limit frame length to N bytes (l>=L) (Z)",
- " n send file if source Newer or longer (Z)",
- " N send file if source different length or date (Z)",
- " o Use 16 bit CRC instead of 32 bit CRC (Z)",
- " p Protect existing destination file (Z)",
- " r Resume/Recover interrupted file transfer (Z)",
- " q Quiet (no progress reports)",
- " u Unlink file after transmission",
- " v Verbose - debugging information",
- " X XMODEM protocol - send no pathnames",
- #ifdef MSDOS
- " Y YMODEM protocol",
- #endif
- " y Yes, overwrite existing file (Z)",
- "- as pathname sends standard input as sPID.sz or environment ONAME",
- ""
- };
-
- usage()
- {
- char **pp;
-
- for (pp = babble; **pp; ++pp)
- fprintf(stderr, "%s\n", *pp);
- fprintf(stderr, "%s for %s by Chuck Forsberg\n", VERSION, OS);
- exit(1);
- }
-
- /*
- * Get the receiver's init parameters
- */
- getzrxinit()
- {
- int n;
- struct stat f;
-
- for (n = 10; --n >= 0; )
- {
-
- switch (zgethdr(Rxhdr, 1))
- {
- case ZCHALLENGE: /* Echo receiver's challenge numbr */
- stohdr(Rxpos);
- zshhdr(ZACK, Txhdr);
- continue;
- case ZCOMMAND: /* They didn't see out ZRQINIT */
- stohdr(0L);
- zshhdr(ZRQINIT, Txhdr);
- continue;
- case ZRINIT:
- Rxflags = 0377 & Rxhdr[ZF0];
- if (Wantfcs32 && (Rxflags & CANFC32))
- Txfcs32 = TRUE;
- Rxbuflen = (0377 & Rxhdr[ZP0])+((0377 & Rxhdr[ZP1]) << 8);
- vfile("Rxbuflen=%d Tframlen=%d", Rxbuflen, Tframlen);
- if (!Fromcu)
- signal(SIGINT, SIG_IGN);
- #ifndef READCHECK
- #ifdef USG
- mode(2); /* Set cbreak, XON/XOFF, etc. */
- #else
- /* Use 1024 byte frames if no sample/interrupt */
- if (Rxbuflen < 32 || Rxbuflen > 1024)
- {
- Rxbuflen = 1024;
- vfile("Rxbuflen=%d", Rxbuflen);
- }
- #endif
- #endif
- /* Override to force shorter frame length */
- if (Rxbuflen && (Rxbuflen > Tframlen) && (Tframlen >= 32))
- Rxbuflen = Tframlen;
- if (!Rxbuflen && (Tframlen >= 32) && (Tframlen <= 1024))
- Rxbuflen = Tframlen;
- vfile("Rxbuflen=%d", Rxbuflen);
- #ifndef MSDOS
- /* If using a pipe for testing set lower buf len */
- fstat(iofd, &f);
- if ((f.st_mode & S_IFMT) != S_IFCHR
- && (Rxbuflen == 0 || Rxbuflen > 4096))
- Rxbuflen = 4096;
- #endif
- /*
- * If input is not a regular file, force ACK's each 1024
- * (A smarter strategey could be used here ...)
- */
- fstat(fileno(in), &f);
- if (((f.st_mode & S_IFMT) != S_IFREG)
- && (Rxbuflen == 0 || Rxbuflen > 1024))
- Rxbuflen = 1024;
- vfile("Rxbuflen=%d", Rxbuflen);
-
- return(sendzsinit());
- case ZCAN:
- case TIMEOUT:
- return(ERROR);
- case ZRQINIT:
- if (Rxhdr[ZF0] == ZCOMMAND)
- continue;
- default:
- zshhdr(ZNAK, Txhdr);
- continue;
- }
- }
- return(ERROR);
- }
-
- /* Send send-init information */
- sendzsinit()
- {
- int c;
- int errors;
-
- if (Myattn[0] == '\0')
- return(OK);
- errors = 0;
- for (;;)
- {
- stohdr(0L);
- zsbhdr(ZSINIT, Txhdr);
- zsdata(Myattn, 1+strlen(Myattn), ZCRCW);
- c = zgethdr(Rxhdr, 1);
- switch (c)
- {
- case ZCAN:
- return(ERROR);
- case ZACK:
- return(OK);
- default:
- if (++errors > 9)
- return(ERROR);
- continue;
- }
- }
- }
-
- /* Send file name and related info */
- zsendfile(buf, blen)
- char *buf;
- {
- int c;
-
- for (;;)
- {
- Txhdr[ZF0] = Lzconv; /* file conversion request */
- Txhdr[ZF1] = Lzmanag; /* file management request */
- Txhdr[ZF2] = Lztrans; /* file transport request */
- Txhdr[ZF3] = 0;
- zsbhdr(ZFILE, Txhdr);
- zsdata(buf, blen, ZCRCW);
- again:
- c = zgethdr(Rxhdr, 1);
- switch (c)
- {
- case ZRINIT:
- goto again;
- case ZCAN:
- case TIMEOUT:
- case ZABORT:
- case ZFIN:
- return(ERROR);
- case ZSKIP:
- fclose(in);
- return(c);
- case ZRPOS:
- fseek(in, Rxpos, 0);
- Txpos = Rxpos;
- Lastc = -1;
- Dontread = FALSE;
- return zsendfdata();
- case ERROR:
- default:
- continue;
- }
- }
- }
-
- /* Send the data in the file */
- zsendfdata()
- {
- int c, e;
- int newcnt;
- long tcount = 0;
- static int tleft = 6; /* Counter for test mode */
-
- if (Baudrate > 300)
- blklen = 256;
- if (Baudrate > 2400)
- blklen = KSIZE;
- if (Rxbuflen && blklen>Rxbuflen)
- blklen = Rxbuflen;
- if (blkopt && blklen > blkopt)
- blklen = blkopt;
- vfile("Rxbuflen=%d blklen=%d", Rxbuflen, blklen);
- somemore:
- if (setjmp(intrjmp))
- {
- waitack:
- c = getinsync();
- switch (c)
- {
- default:
- case ZCAN:
- fclose(in);
- return(ERROR);
- case ZSKIP:
- fclose(in);
- return(c);
- case ZACK:
- case ZRPOS:
- break;
- case ZRINIT:
- return(OK);
- }
- #ifdef READCHECK
- /*
- * If the reverse channel can be tested for data,
- * this logic may be used to detect error packets
- * sent by the receiver, in place of setjmp/longjmp
- * rdchk(fdes) returns non 0 if a character is available
- */
- while (rdchk(iofd))
- {
- #ifdef SVR2
- switch (checked)
- #else
- switch (readline(1))
- #endif
- {
- case CAN:
- case ZPAD:
- goto waitack;
- }
- }
- #endif
- }
-
- if (!Fromcu)
- signal(SIGINT, onintr);
- newcnt = Rxbuflen;
- stohdr(Txpos);
- zsbhdr(ZDATA, Txhdr);
-
- /*
- * Special testing mode. This should force receiver to Attn,ZRPOS
- * many times. Each time the signal should be caught, causing the
- * file to be started over from the beginning.
- */
- if (Testattn)
- {
- if ( --tleft)
- while (tcount < 20000)
- {
- #ifndef MSDOS
- printf(qbf);
- fflush(stdout);
- #else
- tty_write(iofd, qbf, strlen(qbf));
- #endif
- tcount += strlen(qbf);
- #ifdef READCHECK
- while (rdchk(iofd))
- {
- #ifdef SVR2
- switch (checked)
- #else
- switch (readline(1))
- #endif
- {
- case CAN:
- case ZPAD:
- #ifdef TCFLSH
- ioctl(iofd, TCFLSH, 1);
- #endif
- goto waitack;
- }
- }
- #endif
- }
- signal(SIGINT, SIG_IGN);
- canit();
- sleep(3);
- purgeline();
- mode(0);
- printf("\nsz: Tcount = %ld\n", tcount);
- if (tleft)
- {
- printf("ERROR: Interrupts Not Caught\n");
- exit(1);
- }
- exit(0);
- }
-
- do
- {
- if (Dontread)
- c = Lastc;
- else
- {
- c = zfilbuf(txbuf, blklen);
- Lastread = Txpos;
- Lastc = c;
- }
- if (Verbose > 10)
- vfile("Dontread=%d c=%d", Dontread, c);
- Dontread = FALSE;
- if (c < blklen)
- e = ZCRCE;
- else if (Rxbuflen && (newcnt -= c) <= 0)
- e = ZCRCW;
- else
- e = ZCRCG;
- zsdata(txbuf, c, e);
- Txpos += c;
- if (e == ZCRCW)
- goto waitack;
- #ifdef READCHECK
- /*
- * If the reverse channel can be tested for data,
- * this logic may be used to detect error packets
- * sent by the receiver, in place of setjmp/longjmp
- * rdchk(fdes) returns non 0 if a character is available
- */
- fflush(stdout);
- while (rdchk(iofd))
- {
- #ifdef SVR2
- switch (checked)
- #else
- switch (readline(1))
- #endif
- {
- case CAN:
- case ZPAD:
- #ifdef TCFLSH
- ioctl(iofd, TCFLSH, 1);
- #endif
- /* zcrce - dinna wanna start a ping-pong game */
- zsdata(txbuf, 0, ZCRCE);
- goto waitack;
- }
- }
- #endif
- }
- while (c == blklen);
- if (!Fromcu)
- signal(SIGINT, SIG_IGN);
-
- for (;;)
- {
- stohdr(Txpos);
- zsbhdr(ZEOF, Txhdr);
- switch (getinsync())
- {
- case ZACK:
- continue;
- case ZRPOS:
- goto somemore;
- case ZRINIT:
- return(OK);
- case ZSKIP:
- fclose(in);
- return(c);
- default:
- fclose(in);
- return(ERROR);
- }
- }
- }
-
- /*
- * Respond to receiver's complaint, get back in sync with receiver
- */
- getinsync()
- {
- int c;
-
- for (;;)
- {
- if (Testattn)
- {
- #ifndef MSDOS
- printf("\r\n\n\n***** Signal Caught *****\r\n");
- #else
- tty_write(iofd, "\r\n\n\n***** Signal Caught *****\r\n", 31);
- #endif
- Rxpos = 0;
- c = ZRPOS;
- }
- else
- c = zgethdr(Rxhdr, 0);
- switch (c)
- {
- case ZCAN:
- case ZABORT:
- case ZFIN:
- case TIMEOUT:
- return(ERROR);
- case ZRPOS:
- if (Lastc >= 0 && Lastread == Rxpos)
- Dontread = TRUE;
- else
- {
- clearerr(in); /* In case file EOF seen */
- fseek(in, Rxpos, 0);
- }
- Txpos = Rxpos;
- return(c);
- case ZACK:
- return(c);
- case ZRINIT:
- case ZSKIP:
- fclose(in);
- return(c);
- case ERROR:
- default:
- zsbhdr(ZNAK, Txhdr);
- continue;
- }
- }
- }
- /* Say "bibi" to the receiver, try to do it cleanly */
- saybibi()
- {
- for (;;)
- {
- stohdr(0L);
- zsbhdr(ZFIN, Txhdr);
- switch (zgethdr(Rxhdr, 0))
- {
- case ZFIN:
- sendline('O');
- sendline('O');
- flushmo();
- case ZCAN:
- case TIMEOUT:
- return;
- }
- }
- }
-
- /* Local screen character display function */
- bttyout(c)
- {
- if (Verbose)
- putc(c, stderr);
- }
-
- /* Send command and related info */
- zsendcmd(buf, blen)
- char *buf;
- {
- int c, errors;
- long cmdnum;
-
- cmdnum = getpid();
- errors = 0;
- for (;;)
- {
- stohdr(cmdnum);
- Txhdr[ZF0] = Cmdack1;
- zsbhdr(ZCOMMAND, Txhdr);
- zsdata(buf, blen, ZCRCW);
- listen:
- Rxtimeout = 100; /* Ten second wait for resp. */
- c = zgethdr(Rxhdr, 1);
-
- switch (c)
- {
- case ZRINIT:
- continue;
- case ERROR:
- case TIMEOUT:
- if (++errors > Cmdtries)
- return(ERROR);
- continue;
- case ZCAN:
- case ZABORT:
- case ZFIN:
- case ZSKIP:
- case ZRPOS:
- return(ERROR);
- default:
- if (++errors > 10)
- return(ERROR);
- continue;
- case ZCOMPL:
- Exitcode = Rxpos;
- saybibi();
- return(OK);
- case ZRQINIT:
- vfile("******** RZ *******");
- system("rz");
- vfile("******** SZ *******");
- goto listen;
- }
- }
- }
-
- /*
- * If called as sb use YMODEM protocol
- */
- chkinvok(s)
- char *s;
- {
- char *p;
-
- p = s;
- while (*p == '-')
- s = ++p;
- while (*p)
- if (*p++ == '/')
- s = p;
- if (*s == 'v')
- {
- Verbose=1;
- ++s;
- }
- Progname = s;
- if (s[0] == 's' && s[1] == 'b')
- {
- Nozmodem = TRUE;
- blklen=KSIZE;
- }
- }